﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Xml;
using System.IO;
using TSL_Tools.SqlTools;

namespace ReportingEngine
{
    public partial class TSL_ReportingEngine
    {
        //=================================================================================================
        #region SQL Code Update methods
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]
        public bool GetReportingEngineVersion(string expectedVersion)
        {
            
            // Does the SPROC exist?
            string retVal;
            tts.ExecuteScalarString(Sql_CHECKFORINSTALLEDREPORTING, out retVal);
            if (retVal == "")
                return false;

            // Now get and compare the version.
            string sVersion;
            tts.ExecuteScalarString(Sql_GETTSLREPORTINGVERSION, out sVersion);

            if (sVersion.ToLower() == expectedVersion.ToLower())
                return true;
            else
                return false;
        }

        public TimeSpan UpdateReportingEngine(out string results)
        {
            DateTime dt = DateTime.Now;
            
            // First, clean up the old sprocs
            string sqlCmd = Sql_DELETEALLOLDSTOREDPROCEDURES;
            tts.ExecuteNoReturn(sqlCmd);
            mostRecentSqlQuery = sqlCmd;

            // Next, clean up the old views
            sqlCmd = Sql_DELETEALLOLDVIEWS;
            tts.ExecuteNoReturn(sqlCmd);
            mostRecentSqlQuery = sqlCmd;

            // Next, clean up the old tables
            sqlCmd = Sql_DELETEALLOLDTABLES;
            tts.ExecuteNoReturn(sqlCmd);
            mostRecentSqlQuery = sqlCmd;

            // Finally, add all of the new stuff
            results = UpdateTheSprocs();

            return (TimeSpan)(DateTime.Now - dt);
        }

        public int GetNumberOfCoreRowsThatNeedUpdating()
        {
            string sqlCmd = "SELECT COUNT (LoadTestRunId) FROM LoadTestRun WHERE LoadTestRunId NOT IN (SELECT LoadTestRunId FROM TSL_LoadTestCoreInfo)";
            int x;
            tts.ExecuteScalarInt32(sqlCmd, out x);
            return x;
        }

        private string UpdateTheSprocs()
        {
            StringBuilder sb = new StringBuilder();

            string[] sFiles = Directory.GetFiles(Environment.CurrentDirectory + SqlScriptLocation, "*.sql");
            int iNumQueries = 0;
            string sReturn = "";
            foreach (string sFile in sFiles)
            {
                // The below line is for debugging purposes only
                //MessageBox.Show("Reading file: " + sFile, "Database Code Updates");
                using (StreamReader sr = new StreamReader(sFile))
                {
                    string sFileContents = sr.ReadToEnd();
                    if (sFileContents.Contains(Sql_QUERY_SECTION_DELIMITER))
                    {
                        if (LoadTestDatabaseName != "LoadTest2010") // In case the database name is not LoadTest2010
                            sFileContents = sFileContents.Replace("LoadTest2010", LoadTestDatabaseName);

                        sFileContents = sFileContents.Substring(sFileContents.IndexOf(Sql_QUERY_SECTION_DELIMITER));
                        int x = 0;
                        foreach (string str in sFileContents.Split(new string[] { Sql_QUERY_SECTION_DELIMITER }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            string sSqlCmd = str.Substring(0, str.IndexOf(Sql_QUERY_DELIMITER));
                            tts.ExecuteNoReturn(sSqlCmd);
                            x++;
                            //Track the items that were added.
                            int iStart = sSqlCmd.IndexOf("CREATE ", StringComparison.CurrentCulture);
                            if (iStart != -1) // Eliminates all the calls to "Grant Access"
                            {
                                iStart += 7; //Get past the word 'CREATE '
                                int iEnd = sSqlCmd.IndexOf("\n", iStart);
                                if (iEnd > iStart)
                                    sb.Append(sSqlCmd.Substring(iStart, iEnd - iStart));
                                else
                                    sb.Append(sSqlCmd.Substring(iStart));
                            }
                        }
                        iNumQueries += x;
                    }
                }
            }
            sReturn = String.Format(Msg_DATABASEUPDATEINFORMATION, LoadTestDatabaseName, sb.ToString(), iNumQueries);
            return sReturn;
        }

        public async Task<TimeSpan> UpdateTheCoreInfoTablesAsync()
        {
            var s = await Task.Run(() => UpdateTheCoreInfoTables());
            return s;

        }

        public TimeSpan UpdateTheCoreInfoTables()
        {
            DateTime dt = DateTime.Now;

            tts.ExecuteNoReturn(Sql_UPDATELOADTESTCOREINFO);
            //AddConstantLoadIntervals();
            return (TimeSpan)(DateTime.Now - dt);
        }
        #endregion

        #region Read and configure the user settings
        private void GetExtendedSettings()
        {
            try
            {
                XmlDocument xDoc = new XmlDocument();
                xDoc.Load("Charting\\ExtendedSettings.xml");

                #region -- ScoreCard Settings ------------------------------------------------------------
                /*<ScoreCardItem 
                 * Name="LoadTestRunId" 
                 * DataType="int" 
                 * UseInReport="True" 
                 * ShowGraph="false" 
                 * ShowGoal="false" 
                 * Goal="1" 
                 * HigherIsBetter="true" 
                 * YAxisMax="" 
                 * Title="Load Test Run Id" 
                 * Description="The run ID of the test"></ScoreCardItem> */

                ScoreCardItems.Clear();
                foreach (XmlNode xNode in xDoc.GetElementsByTagName("ScoreCardItem"))
                {
                    ScoreCardItem item = new ScoreCardItem();
                    item.Name = xNode.Attributes["Name"].Value;
                    item.DataType = xNode.Attributes["DataType"].Value;
                    item.UseInReport = xNode.Attributes["UseInReport"].Value.ToLower() == "true" ? true : false;
                    item.ShowGraph = xNode.Attributes["ShowGraph"].Value.ToLower() == "true" ? true : false;
                    item.ShowGoal = xNode.Attributes["ShowGoal"].Value.ToLower() == "true" ? true : false;
                    item.Goal = xNode.Attributes["Goal"].Value != "" ? Convert.ToDouble(xNode.Attributes["Goal"].Value) : 0;
                    item.HigherIsBetter = xNode.Attributes["HigherIsBetter"].Value.ToLower() == "true" ? true : false;
                    item.YAxisMax = xNode.Attributes["YAxisMax"].Value != "" ? Convert.ToInt32(xNode.Attributes["YAxisMax"].Value) : 0;
                    item.Title = xNode.Attributes["Title"].Value;
                    item.Description = xNode.Attributes["Description"].Value;
                    ScoreCardItems.Add(item);
                }
                #endregion
            }
            catch (XmlException ex)
            {
                throw new XmlException("XML Parsing exception on ExtendedSettings.XML", ex);
            }
        }

        public bool UpdateSqlConfigSettings(string sqlConnection, int connectionTimeout, int commandTimeout, bool reloadCoreInfo)
        {
            bool configChangeSuccessful = false;

            sqlConn = sqlConnection;
            connTimeout = connectionTimeout;
            cmdTimeout = commandTimeout;

            tts = new TalkToSql(sqlConn, connTimeout, cmdTimeout);

            if (reloadCoreInfo)
            {
                listOfRuns.Clear();  // = new Dictionary<int, LoadTestCoreInfo>();
                xDoc.RemoveAll(); //= new XmlDocument();
                ScoreCardItems.Clear(); //= new List<ScoreCardItem>();
            }

            return configChangeSuccessful;
        }
        #endregion
    }
}
